package web

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"
)

// FileServerConfig 表示文件服务器配置
type FileServerConfig struct {
	Port            int    `json:"port"`
	Enabled         bool   `json:"enabled"`
	BasePath        string `json:"base_path"` // 服务器上的基础路径
	URLPath         string `json:"url_path"`  // URL访问路径
	AllowDirListing bool   `json:"allow_dir_listing"` // 是否允许目录浏览
}

var (
	fileConfigLock     sync.Mutex
	fileConfigFilePath string
	fileServerConfig   *FileServerConfig
	fileServerRunning  bool
)

// 加载文件服务器配置文件
func LoadFileServerConfig(filename string) (*FileServerConfig, error) {
	fileConfigLock.Lock()
	defer fileConfigLock.Unlock()
	
	fileConfigFilePath = filename
	
	// 创建默认配置
	defaultConfig := &FileServerConfig{
		Enabled:         false,
		Port:            8081,
		BasePath:        "",
		URLPath:         "/files",
		AllowDirListing: false,
	}
	
	file, err := os.Open(filename)
	if err != nil {
		if os.IsNotExist(err) {
			// 如果配置文件不存在，使用默认配置
			fileServerConfig = defaultConfig
			
			// 保存默认配置
			SaveFileServerConfig(fileServerConfig)
			return fileServerConfig, nil
		}
		// 其他错误，但仍使用默认配置
		fileServerConfig = defaultConfig
		return fileServerConfig, err
	}
	defer file.Close()

	// 尝试解析JSON
	config := &FileServerConfig{}
	decoder := json.NewDecoder(file)
	err = decoder.Decode(config)
	if err != nil {
		// JSON解析错误，使用默认配置
		log.Printf("解析文件服务器配置文件失败: %v，将使用默认配置", err)
		fileServerConfig = defaultConfig
		return fileServerConfig, err
	}
	
	fileServerConfig = config
	return config, nil
}

// 保存文件服务器配置文件
func SaveFileServerConfig(config *FileServerConfig) error {
	fileConfigLock.Lock()
	defer fileConfigLock.Unlock()
	
	// 创建目录(如果不存在)
	dir := filepath.Dir(fileConfigFilePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return err
	}
	
	// 创建临时文件
	tempFile, err := os.CreateTemp(dir, "fileserver-config-*.json")
	if err != nil {
		return err
	}
	tempFileName := tempFile.Name()
	
	// 写入配置数据
	encoder := json.NewEncoder(tempFile)
	encoder.SetIndent("", "  ")
	if err := encoder.Encode(config); err != nil {
		tempFile.Close()
		os.Remove(tempFileName)
		return err
	}
	
	// 关闭临时文件
	if err := tempFile.Close(); err != nil {
		os.Remove(tempFileName)
		return err
	}
	
	// 重命名临时文件
	if err := os.Rename(tempFileName, fileConfigFilePath); err != nil {
		os.Remove(tempFileName)
		return err
	}
	
	fileServerConfig = config
	return nil
}

// StartFileServer 启动一个静态文件服务器
func StartFileServer() error {
	// 确保配置已加载，如果未加载则使用默认配置
	if fileServerConfig == nil {
		fileServerConfig = &FileServerConfig{
			Enabled:         false,
			Port:            8081,
			BasePath:        "",
			URLPath:         "/files",
			AllowDirListing: false,
		}
		log.Printf("未找到文件服务器配置，使用默认配置")
	}
	
	// 如果文件服务器已经在运行，先确认它被停止
	if fileServerRunning {
		log.Printf("文件服务器已在运行，无法启动新实例")
		return fmt.Errorf("文件服务器已在运行")
	}
	
	if !fileServerConfig.Enabled {
		log.Printf("文件服务器已禁用，不会启动")
		return nil
	}

	basePath := fileServerConfig.BasePath
	urlPath := fileServerConfig.URLPath
	port := fileServerConfig.Port
	allowDirListing := fileServerConfig.AllowDirListing
	
	// 检查基础路径是否存在
	if basePath == "" {
		log.Printf("文件服务器基础路径未设置")
		return fmt.Errorf("文件服务器基础路径未设置")
	}
	
	if _, err := os.Stat(basePath); os.IsNotExist(err) {
		log.Printf("文件服务器基础路径不存在: %s", basePath)
		return fmt.Errorf("基础路径不存在: %s", basePath)
	}

	// 确保URL路径以"/"开头，不以"/"结尾
	if !strings.HasPrefix(urlPath, "/") {
		urlPath = "/" + urlPath
	}
	urlPath = strings.TrimSuffix(urlPath, "/")

	// 创建文件服务器
	fileServer := http.FileServer(neuteredFileSystem{http.Dir(basePath), allowDirListing})

	// 创建一个新的ServeMux
	mux := http.NewServeMux()

	// 注册处理函数
	mux.HandleFunc(urlPath+"/", func(w http.ResponseWriter, r *http.Request) {
		// 从请求路径中移除URL路径前缀
		r.URL.Path = strings.TrimPrefix(r.URL.Path, urlPath)
		if r.URL.Path == "" || r.URL.Path == "/" {
			r.URL.Path = "/"
		}
		
		// 启用CORS
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
		
		// 处理OPTIONS请求
		if r.Method == "OPTIONS" {
			w.WriteHeader(http.StatusOK)
			return
		}
		
		fileServer.ServeHTTP(w, r)
	})

	// 在新的goroutine中启动HTTP服务器
	go func() {
		addr := fmt.Sprintf(":%d", port)
		fileServerRunning = true
		log.Printf("文件服务器已启动，访问地址: http://localhost%s%s", addr, urlPath)
		
		err := http.ListenAndServe(addr, mux)
		if err != nil {
			log.Printf("文件服务器停止: %v", err)
		}
		fileServerRunning = false
	}()

	return nil
}

// RestartFileServer 重启文件服务器
func RestartFileServer() error {
	// 文件服务器不需要真正"停止"，因为我们只是创建一个新的实例
	fileServerRunning = false
	return StartFileServer()
}

// GetFileServerConfig 获取当前文件服务器配置
func GetFileServerConfig() *FileServerConfig {
	fileConfigLock.Lock()
	defer fileConfigLock.Unlock()
	return fileServerConfig
}

// UpdateFileServerConfig 更新文件服务器配置并重新启动服务
func UpdateFileServerConfig(config *FileServerConfig) error {
	// 保存新配置
	err := SaveFileServerConfig(config)
	if err != nil {
		return err
	}
	
	// 重启文件服务器
	return RestartFileServer()
}

// neuteredFileSystem 是一个自定义的文件系统，可以控制是否允许目录浏览
type neuteredFileSystem struct {
	fs http.FileSystem
	allowDirListing bool
}

// Open 打开文件或目录
func (nfs neuteredFileSystem) Open(path string) (http.File, error) {
	// 打开请求的文件
	f, err := nfs.fs.Open(path)
	if err != nil {
		return nil, err
	}

	// 获取文件信息
	s, err := f.Stat()
	if err != nil {
		f.Close()
		return nil, err
	}
	
	// 如果是目录且不允许目录浏览，返回一个"空"的目录，它的Readdir方法会返回空列表
	if s.IsDir() && !nfs.allowDirListing {
		return &neuteredReaddirFile{f}, nil
	}

	return f, nil
}

// neuteredReaddirFile 是一个包装了http.File的结构体，它的Readdir方法返回空列表
type neuteredReaddirFile struct {
	http.File
}

// Readdir 覆盖http.File的Readdir方法，返回空列表，禁止目录浏览
func (f *neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) {
	return []os.FileInfo{}, nil
} 